//-----------------------------------------------------------------------------
#include <QPaintEvent>
#include <QResizeEvent>
#include <QPainter>
#include <QtDebug>
#include <QMap>
#include "CScreen.h"
//-----------------------------------------------------------------------------
#define NB_DIGIT_X                  5
#define NB_DIGIT_Y                  7
#define DIGIT_SIZE                  3
#define DIGIT_SPACE                 2
#define DIGIT_ALL_SIZE              (DIGIT_SIZE+DIGIT_SPACE)
#define SPACE                       4
#define CAR_HEIGHT                  (NB_DIGIT_Y*DIGIT_SIZE+(NB_DIGIT_Y-1)*DIGIT_SPACE)
#define CAR_WIDTH                   (NB_DIGIT_X*DIGIT_SIZE+(NB_DIGIT_X-1)*DIGIT_SPACE)
#define WIDTH                       (CAR_WIDTH+SPACE)
#define HEIGHT                      (CAR_HEIGHT+SPACE+2)
#define SCREEN_HEIGHT               ((MAX_VALUES+2)*HEIGHT)
//-----------------------------------------------------------------------------
typedef bool matrice_car_type[NB_DIGIT_Y][NB_DIGIT_X];
//-----------------------------------------------------------------------------
static QMap<QChar, int> mapIdx;
//-----------------------------------------------------------------------------
static matrice_car_type matrice_cars[14] =   {
                                                { //0
                                                    {false, true, true, true, false},
                                                    {true, false, false, false, true},
                                                    {true, false, false, false, true},
                                                    {true, false, false, false, true},
                                                    {true, false, false, false, true},
                                                    {true, false, false, false, true},
                                                    {false, true, true, true, false}
                                                },
                                                { //1
                                                    {false, false, true, false, false},
                                                    {false, true, true, false, false},
                                                    {false, false, true, false, false},
                                                    {false, false, true, false, false},
                                                    {false, false, true, false, false},
                                                    {false, false, true, false, false},
                                                    {false, true, true, true, false},
                                                },
                                                { //2
                                                    {false, true, true, true, false},
                                                    {true, false, false, false, true},
                                                    {false, false, false, false, true},
                                                    {false, false, false, true, false},
                                                    {false, false, true, false, false},
                                                    {false, true, false, false, false},
                                                    {true, true, true, true, true},
                                                },
                                                { //3
                                                    {true, true, true, true, true},
                                                    {false, false, false, true, false},
                                                    {false, false, true, false, false},
                                                    {false, false, false, true, false},
                                                    {false, false, false, false, true},
                                                    {true, false, false, false, true},
                                                    {false, true, true, true, false},
                                                },
                                                { //4
                                                    {false, false, false, true, false},
                                                    {false, false, true, true, false},
                                                    {false, true, false, true, false},
                                                    {true, false, false, true, false},
                                                    {true, true, true, true, true},
                                                    {false, false, false, true, false},
                                                    {false, false, false, true, false},
                                                },
                                                { //5
                                                    {true, true, true, true, true},
                                                    {true, false, false, false, false},
                                                    {true, true, true, true, false},
                                                    {false, false, false, false, true},
                                                    {false, false, false, false, true},
                                                    {true, false, false, false, true},
                                                    {false, true, true, true, false},
                                                },
                                                { //6
                                                    {false, false, true, true, false},
                                                    {false, true, false, false, false},
                                                    {true, false, false, false, false},
                                                    {true, true, true, true, false},
                                                    {true, false, false, false, true},
                                                    {true, false, false, false, true},
                                                    {false, true, true, true, false},
                                                },
                                                { //7
                                                    {true, true, true, true, true},
                                                    {false, false, false, false, true},
                                                    {false, false, false, true, false},
                                                    {false, false, true, false, false},
                                                    {false, true, false, false, false},
                                                    {false, true, false, false, false},
                                                    {false, true, false, false, false},
                                                },
                                                { //8
                                                    {false, true, true, true, false},
                                                    {true, false, false, false, true},
                                                    {true, false, false, false, true},
                                                    {false, true, true, true, false},
                                                    {true, false, false, false, true},
                                                    {true, false, false, false, true},
                                                    {false, true, true, true, false},
                                                },
                                                { //9
                                                    {false, true, true, true, false},
                                                    {true, false, false, false, true},
                                                    {true, false, false, false, true},
                                                    {false, true, true, true, true},
                                                    {false, false, false, false, true},
                                                    {false, false, false, true, false},
                                                    {false, true, true, false, false},
                                                },
                                                { //.
                                                    {false, false, false, false, false},
                                                    {false, false, false, false, false},
                                                    {false, false, false, false, false},
                                                    {false, false, false, false, false},
                                                    {false, false, false, false, false},
                                                    {false, true, true, false, false},
                                                    {false, true, true, false, false},
                                                },
                                                { //E
                                                    {true, true, true, true, true},
                                                    {true, false, false, false, false},
                                                    {true, false, false, false, false},
                                                    {true, true, true, true, false},
                                                    {true, false, false, false, false},
                                                    {true, false, false, false, false},
                                                    {true, true, true, true, true},
                                                },
                                                { //+
                                                    {false, false, false, false, false},
                                                    {false, false, true, false, false},
                                                    {false, false, true, false, false},
                                                    {true, true, true, true, true},
                                                    {false, false, true, false, false},
                                                    {false, false, true, false, false},
                                                    {false, false, false, false, false},
                                                },
                                                { //-
                                                    {false, false, false, false, false},
                                                    {false, false, false, false, false},
                                                    {false, false, false, false, false},
                                                    {true, true, true, true, true},
                                                    {false, false, false, false, false},
                                                    {false, false, false, false, false},
                                                    {false, false, false, false, false},
                                                }
                                            };
//-----------------------------------------------------------------------------
CScreen::CScreen(QWidget *parent) : QWidget(parent), currentNumber() {
    mapIdx.insert('0', 0);
    mapIdx.insert('1', 1);
    mapIdx.insert('2', 2);
    mapIdx.insert('3', 3);
    mapIdx.insert('4', 4);
    mapIdx.insert('5', 5);
    mapIdx.insert('6', 6);
    mapIdx.insert('7', 7);
    mapIdx.insert('8', 8);
    mapIdx.insert('9', 9);
    mapIdx.insert('.', 10);
    mapIdx.insert('E', 11);
    mapIdx.insert('+', 12);
    mapIdx.insert('-', 13);

    clear();

    isOnEdit = false;

    timer = new QTimer(this);
    timer->setInterval(300);
    connect(timer, SIGNAL(timeout()), this, SLOT(redrawCursor()));
    timer->start();

    setMaximumHeight(SCREEN_HEIGHT);
    setMinimumHeight(SCREEN_HEIGHT);
}
//-----------------------------------------------------------------------------
void CScreen::push(const CMyDouble& value) {
    values.insert(0, value);

    repaint(pileRect);
}
//-----------------------------------------------------------------------------
CMyDouble CScreen::pop(void) {
    CMyDouble value;
    if(values.size() >= 1) {
        value = values.takeFirst();

        repaint(pileRect);
    }

    return value;
}
//-----------------------------------------------------------------------------
void CScreen::swap(void) {
    if(values.size() > 1) {
        values.swap(0, 1);

        repaint(pileRect);
    }
}
//-----------------------------------------------------------------------------
void CScreen::clear(void){
    values.clear();

    repaint(pileRect);
}
//-----------------------------------------------------------------------------
void CScreen::setCurrentNumber(CMyDouble currentNumber) {
    this->currentNumber = currentNumber;
    isOnEdit = !currentNumber.isNull();

    repaint(promptRect);
}
//-----------------------------------------------------------------------------
void CScreen::paintEvent(QPaintEvent *event) {
    int i;
    QPainter painter(this);

    for(i=0;i<event->region().rectCount();i++) {
        QRect r = event->region().rects().at(i);

        if(r.contains(errRect)) {
            paintErr(&painter);
        }

        if(r.contains(pileRect)) {
            paintPile(&painter);
        }

        if(r.contains(promptRect)) {
            paintPrompt(&painter);
        }

        if(r.contains(cursorRect)) {
            paintCursor(&painter);
        }
    }

}
//-----------------------------------------------------------------------------
void CScreen::resizeEvent(QResizeEvent *event) {
    if(event->size().height() != SCREEN_HEIGHT) {
        event->ignore();

        return;
    }

    errRect = QRect(0, 0, width(), HEIGHT-1);
    pileRect = QRect(0, HEIGHT, width(), height()-(HEIGHT*2)-2);
    promptRect = QRect(0, height()-HEIGHT-1, width()-CAR_WIDTH-1, HEIGHT);
    cursorRect = QRect(width()-CAR_WIDTH, height()-HEIGHT-1, CAR_WIDTH, HEIGHT);

    QWidget::resizeEvent(event);
}
//-----------------------------------------------------------------------------
void CScreen::draw(QPainter *painter, char c, int xOrig, int yOrig) {
    matrice_car_type *car = &matrice_cars[mapIdx.value(c)];
    int x, y;
    int ix, iy;

    painter->setBrush(QBrush(Qt::gray));
    painter->setPen(QPen(Qt::gray));

    for(iy = 0, y = yOrig;iy<NB_DIGIT_Y;iy++, y += DIGIT_ALL_SIZE) {
        for(ix = 0, x = xOrig;ix<NB_DIGIT_X;ix++, x+= DIGIT_ALL_SIZE) {
            if((*car)[iy][ix]) {
                QRect r(x, y, DIGIT_SIZE, DIGIT_SIZE);

                painter->drawRect(r);
            }
        }
    }
}
//-----------------------------------------------------------------------------
void CScreen::paintErr(QPainter *painter) {
    painter->setBrush(QBrush(Qt::white));
    painter->setPen(QPen(Qt::white));

    painter->drawRect(errRect);

    painter->setPen(QPen(Qt::black));
    painter->drawLine(errRect.x()+4, errRect.height(), errRect.width()-4, errRect.height());
}
//-----------------------------------------------------------------------------
void CScreen::paintPile(QPainter *painter) {
    int i;

    painter->setBrush(QBrush(Qt::white));
    painter->setPen(QPen(Qt::white));

    painter->drawRect(pileRect);

    painter->setBrush(QBrush(Qt::gray));
    painter->setPen(QPen(Qt::gray));

    for(i=0;i<MAX_VALUES && i<values.length();i++) {
        CMyDouble value = values.at(i);
        QString sValue = value.toString();
        int x, y, j;

        if(value.isNull()) {
           break;
        }

        x = pileRect.width() - WIDTH;
        y = (MAX_VALUES-i)*HEIGHT+1;

        for(j=sValue.length()-1;j>=0;j--) {
            draw(painter, sValue.at(j).toAscii(), x ,y);

            x-=WIDTH;
        }
    }
}
//-----------------------------------------------------------------------------
void CScreen::paintPrompt(QPainter *painter) {
    painter->setBrush(QBrush(Qt::white));
    painter->setPen(QPen(Qt::white));

    painter->drawRect(promptRect);

    painter->setPen(QPen(Qt::black));
    painter->drawLine(promptRect.x()+4, promptRect.y(), promptRect.width(), promptRect.y());

    painter->setBrush(QBrush(Qt::gray));
    painter->setPen(QPen(Qt::gray));

    if(!currentNumber.isNull()) {
        QString sValue = currentNumber.toString();
        int x, y, j;

        x = promptRect.width() - WIDTH;
        y = height()-HEIGHT+1;

        for(j=sValue.length()-1;j>=0;j--) {
            draw(painter, sValue.at(j).toAscii(), x ,y);

            x-=WIDTH;
        }
    }
}
//-----------------------------------------------------------------------------
void CScreen::paintCursor(QPainter *painter) {
    static bool cursorVisible = true;

    painter->setBrush(QBrush(Qt::white));
    painter->setPen(QPen(Qt::white));

    painter->drawRect(cursorRect);

    painter->setPen(QPen(Qt::black));
    painter->drawLine(cursorRect.x(), cursorRect.y(), cursorRect.x()+cursorRect.width()-4, cursorRect.y());

    painter->setBrush(QBrush(Qt::gray));
    painter->setPen(QPen(Qt::gray));

    if(cursorVisible) {
        painter->drawRect(cursorRect.x(), cursorRect.y()+cursorRect.height()-DIGIT_SPACE-1, CAR_WIDTH-DIGIT_SPACE, DIGIT_SPACE);
    }

    cursorVisible = !cursorVisible;
}
//-----------------------------------------------------------------------------
void CScreen::redrawCursor(void) {
    repaint(cursorRect);
}
//-----------------------------------------------------------------------------
